--[[
Name: Stitch-1.0
Revision: $Rev: 2 $
Author(s): Nymbia (nymbia@gmail.com)
Website: http://www.wowace.com/wiki/StitchLib
Documentation: http://www.wowace.com/wiki/Stitch-1.0
SVN: http://svn.wowace.com/wowace/trunk/StitchLib/Stitch-1.0/
Description: Library for tradeskill information access and queueing.
Dependencies: AceLibrary, AceEvent-2.0
]]
local MAJOR_VERSION = "Stitch-1.0"
local MINOR_VERSION = "$Rev: 2 $"

if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
if not AceLibrary:HasInstance("AceLocale-2.2") then error(MAJOR_VERSION .. " requires AceLocale-2.2") end
if not AceLibrary:HasInstance("AceEvent-2.0") then error(MAJOR_VERSION .. " requires AceEvent-2.0") end
local AceEvent
local ENCHANTING_STRING
local locale = GetLocale()
if locale == "enUS" then
	ENCHANTING_STRING = "Enchanting"
elseif locale == "frFR" then
	ENCHANTING_STRING = "Enchantement"
elseif locale == "deDE" then
	ENCHANTING_STRING = "Verzauberkunst"
elseif locale == "koKR" then
	ENCHANTING_STRING = "마법부여"
elseif locale == "zhCN" then
	ENCHANTING_STRING = "附魔"
elseif locale == "zhTW" then
	ENCHANTING_STRING = "é™„é­”"
end
locale = nil
local Stitch = {}
Stitch.hooks = {}
local oldDoTrade
-----------------------------------
-- Stuff for Addons to Implement --
-----------------------------------
function Stitch:EnableDataGathering(addon)
	if not tostring(addon) then error("Usage: EnableDataGathering('addon')") end
	self.addons[addon] = true
	self:RegisterEvent("TRADE_SKILL_SHOW")
	self:RegisterEvent("CRAFT_SHOW")
	self:RegisterEvent("TRADE_SKILL_UPDATE")
	self:RegisterEvent("CRAFT_UPDATE")
	if not self.data then
		self.data = {}
	end
end
function Stitch:DisableDataGathering(addon)
	if not addon then self.data = nil self.addons = {} return end
	if not tostring(addon) then error("Usage: DisableDataGathering(['addon'])") end
	self.addons[addon] = false
	for k,v in pairs(self.addons) do
		if v then
			return
		end
	end
	self:UnregisterEvent("TRADE_SKILL_SHOW")
	self:UnregisterEvent("CRAFT_SHOW")
	self:UnregisterEvent("TRADE_SKILL_UPDATE")
	self:UnregisterEvent("CRAFT_UPDATE")
	self.data = nil
end
function Stitch:GetItemDataByIndex(profession, index)
	if (not tonumber(index)) or (not self.data[profession]) then error("Usage: GetItemDataByIndex('profession', index)") end
 	if self.data[profession][index] then
 		return self.data[profession][index]
 	else
 		return nil
 	end
end
function Stitch:GetItemDataByName(name)
	if not tostring(name) then error("Usage: GetItemDataByName('name')") end
	for k,v in pairs(self.data) do
		for l,w in pairs(v) do
			if (not tonumber(w)) and w["name"] == name then
				return w
			end
		end
	end
	return nil
end
function Stitch:GetItemDataByPartialName(name)
	if not tostring(name) then error("Usage: GetItemDataByPartialName('name')") end
	local result = {}
	for k,v in pairs(self.data) do
		for l,w in pairs(v) do
			if (not tonumber(w)) and string.find(string.lower(w["name"]), string.lower(name)) then
				table.insert(result,w)
			end
		end
	end
	if table.getn(result) == 0 then
		return nil
	else
		return result
	end
end
function Stitch:GetReagentDataByIndex(profession, skillindex, reagentindex)
	if (not tonumber(skillindex)) or (not tonumber(reagentindex)) or (not self.data[profession]) then error("Usage: GetItemDataByIndex('profession', index)") end
 	if self.data[profession][skillindex][reagentindex] then
 		return self.data[profession][skillindex][reagentindex]
 	else
 		return nil
 	end
end
function Stitch:GetReagentDataByName(name)
	if not tostring(name) then error("Usage: GetItemDataByName('name')") end
	local result = {}
	for k,v in pairs(self.data) do
		for l,w in pairs(v) do
			if (not tonumber(w)) then
				for m,x in pairs(w) do
					if tonumber(m) and x["name"] == name then
						table.insert(result,w)
					end
				end
			end
		end
	end
	if table.getn(result) == 0 then
		return nil
	else
		return result
	end
end
function Stitch:GetReagentDataByPartialName(name)
	if not tostring(name) then error("Usage: GetItemDataByName('name')") end
	local result = {}
	for k,v in pairs(self.data) do
		for l,w in pairs(v) do
			if (not tonumber(w)) then
				for m,x in pairs(w) do
					if tonumber(m) and string.find(string.lower(x["name"]), string.lower(name)) then
						table.insert(result,w)
					end
				end
			end
		end
	end
	if table.getn(result) == 0 then
		return nil
	else
		return result
	end
end
function Stitch:GetQueueInfo()
	return self.queue
end
function Stitch:GetQueueItemInfo(index)
	return self.data[self.queue[index]["profession"]][self.queue[index]["index"]]
end
function Stitch:RemoveFromQueue(index)
	table.remove(self.queue, index)
end
function Stitch:ClearQueue()
	self.queue = {}
end
function Stitch:ProcessQueue()
	if type(self.queue[1]) == "table" then
		self.queuecasting = true
		if StitchContinueFrame then StitchContinueFrame:Hide() end
		return oldDoTrade(self.queue[1]["index"], self.queue[1]["numcasts"])
	end
end
------------
-- Events --
------------
function Stitch:TRADE_SKILL_SHOW()
	self.recenttrade = TradeSkillFrameTitleText:GetText()
	self:ScanTrade()
end
function Stitch:CRAFT_SHOW()
	self.recentcraft = CraftFrameTitleText:GetText()
	self:ScanCraft()
end
function Stitch:TRADE_SKILL_UPDATE()
	local num = GetNumTradeSkills()
	if tonumber(num) and self.recenttrade and num ~= self.data[self.recenttrade]["num"] then
		self:ScanTrade()
	end
end
function Stitch:CRAFT_UPDATE()
	local num = GetNumCrafts()
	if tonumber(num) and self.recentcraft and num ~= self.data[self.recentcraft]["num"] then
		self:ScanCraft()
	end
end
function Stitch:StopCastCheckUnit(unit)
	if unit == "player" then
		self:StopCast()
	end
end
function Stitch:StopCast()
	if self.queuecasting then
		if event == "UNIT_SPELLCAST_FAILED" or event == "UNIT_SPELLCAST_STOP" or event == "UNIT_SPELLCAST_INTERRUPTED" then
			AceEvent:TriggerEvent("Stitch_Queue_Continue", table.getn(self.queue))
			self.queuecasting = false
			return
		end
		self:RemoveFromQueue(1)
		if table.getn(self.queue) >0 then
			AceEvent:TriggerEvent("Stitch_Queue_Continue", table.getn(self.queue))
		else
			AceEvent:TriggerEvent("Stitch_Queue_Complete")
		end
		self.queuecasting = false
	end
end
--------------------
-- Internal Stuff --
--------------------
function Stitch.hooks:DoTradeSkill(orig, index, times)
	if index then self:AddToQueue(index, times) end
	self:ProcessQueue()
end
function Stitch:AddToQueue(index, times)
	if self.queue[1] and self.queue[1]["profession"] ~= self.recenttrade then
		self:ClearQueue()
	end
	if not times then times = 1 end
	table.insert(self.queue, {
		["profession"] = self.recenttrade,
		["index"] = index,
		["numcasts"] = times,
	})
end
function Stitch:ScanCraft()
	local prof = self.recentcraft
	if prof~=ENCHANTING_STRING then
		return
	end
	if not self.data[prof] then
		self.data[prof] = {}
	end
	self.data[prof]["num"] = GetNumCrafts()
	for i=1,self.data[prof]["num"] do
		local skillname, _, skilltype = GetCraftInfo(i)
		if skilltype~="header" and skillname and ((not self.data[prof][i]) or (self.data[prof][i]["name"] ~= skillname)) then
			self.data[prof][i] = {}
			self.data[prof][i]["name"] = skillname
			self.data[prof][i]["index"] = i
			self.data[prof][i]["profession"] = prof
			self.data[prof][i]["difficulty"] = skilltype
			self.data[prof][i]["nummade"] = 1
			self.data[prof][i]["link"] = GetCraftItemLink(i)
			self.data[prof][i]["numreagents"] = GetCraftNumReagents(i)
			local v=(GetCraftSpellFocus(i)) or " "
			if (string.len(v)>2) then
				self.data[prof][i]["tools"] = BuildColoredListString(v)
			else
				self.data[prof][i]["tools"] = nil
			end
			self.data[prof][i]["texture"] = GetCraftIcon(i)
			if not self.data[prof][i]["link"] then
				self.data[prof] = {}
				return
			end
			for j=1,self.data[prof][i]["numreagents"] do
				local rname, rtexture, rcount, _ = GetCraftReagentInfo(i,j)
				self.data[prof][i][j] = {}
				self.data[prof][i][j]["name"] = rname
				self.data[prof][i][j]["link"] = GetCraftReagentItemLink(i,j)
				self.data[prof][i][j]["needed"] = rcount
				self.data[prof][i][j]["texture"] = rtexture
				if not self.data[prof][i][j]["link"] then
					self.data[prof] = {}
					return
				end
			end
		end
	end
end
function Stitch:ScanTrade()
	local prof = self.recenttrade
	if not self.data[prof] then
		self.data[prof] = {}
	end
	self.data[prof]["num"] = GetNumTradeSkills()
	for i=1,self.data[prof]["num"] do
		local skillname, skilltype = GetTradeSkillInfo(i)
		if skilltype~="header" and skillname and ((not self.data[prof][i]) or (self.data[prof][i]["name"] ~= skillname)) then
			self.data[prof][i] = {}
			self.data[prof][i]["name"] = skillname
			self.data[prof][i]["index"] = i
			self.data[prof][i]["profession"] = prof
			self.data[prof][i]["difficulty"] = skilltype
			self.data[prof][i]["nummade"] = GetTradeSkillNumMade(i)
			self.data[prof][i]["link"] = GetTradeSkillItemLink(i)
			self.data[prof][i]["numreagents"] = GetTradeSkillNumReagents(i)
			local v=(GetTradeSkillTools(i)) or " "
			if (string.len(v)>2) then
				self.data[prof][i]["tools"] = BuildColoredListString(v)
			else
				self.data[prof][i]["tools"] = nil
			end
			self.data[prof][i]["texture"] = GetTradeSkillIcon(i)
			if not self.data[prof][i]["link"] then
				self.data[prof] = {}
				return
			end
			for j=1,self.data[prof][i]["numreagents"] do
				local rname, rtexture, rcount, _ = GetTradeSkillReagentInfo(i,j)
				self.data[prof][i][j] = {}
				self.data[prof][i][j]["name"] = rname
				self.data[prof][i][j]["link"] = GetTradeSkillReagentItemLink(i,j)
				self.data[prof][i][j]["needed"] = rcount
				self.data[prof][i][j]["texture"] = rtexture
				if not self.data[prof][i][j]["link"] then
					self.data[prof] = {}
					return
				end
			end
		end
	end
end
----------------------
-- AceLibrary Stuff --
----------------------
local function activate(self, oldLib, oldDeactivate)
	if oldLib then
		self.data = oldLib.data
		self.addons = oldLib.addons
		self.queue = oldLib.queue
		self.queuecasting = oldLib.queuecasting
	else
		oldDoTrade = DoTradeSkill
		function DoTradeSkill(index, times)
			if self.hooks.DoTradeSkill then
				return self.hooks.DoTradeSkill(self, oldDoTrade, index, times)
			else
				return oldDoTrade(index, times)
			end
		end
	end
	if not self.data then
		self.data = {}
	end
	if not self.addons then
		self.addons = {}
	end
	if not self.queue then
		self.queue = {}
	end
	if not self.queuecasting then
		self.queuecasting = false
	end
	if oldDeactivate then
		oldDeactivate(oldLib)
	end
end
local function external(self, major, instance)
	if major == "AceEvent-2.0" then
		AceEvent = instance
		AceEvent:embed(self)
		self:UnregisterAllEvents()
		self:CancelAllScheduledEvents()
		--2.0 events
		self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED", "StopCastCheckUnit")
		self:RegisterEvent("UNIT_SPELLCAST_FAILED", "StopCastCheckUnit")
		self:RegisterEvent("UNIT_SPELLCAST_STOP", "StopCastCheckUnit")
		self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED", "StopCastCheckUnit")
		--1.x events
		self:RegisterEvent("SPELLCAST_INTERRUPTED", "StopCast")
		self:RegisterEvent("SPELLCAST_FAILED", "StopCast")
		self:RegisterEvent("SPELLCAST_STOP", "StopCast")
	end
end
AceLibrary:Register(Stitch, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
Stitch = nil

--[[
self.data = {
	professionname = {
		num = total,
		index = {
			["name"] = itemname,
			["index"] = index,
			["profession"] = profession,
			["difficulty"] = "optimal",
			["nummade"] = nummade,
			["link"] = link,
			["numreagents"] = num,
			["tools"] = "tools",
			["texture"] = "texture",
			[reagentindex] = {
				["name"] = name,
				["link"] = link,
				["needed"] = num,
				["texture"] = texture,
			},
		}
	}
}
self.queue = {
	[numberinline] = {
		["profession"] = profession,
		["index"] = index,
		["numcasts"] = num,
	}
}
]]